package org.moyrax.nereyda.services.factory
{
	import flash.events.Event;
	import flash.net.getClassByAlias;
	
	import mx.collections.ArrayCollection;
	import mx.controls.Alert;
	
	import org.moyrax.nereyda.lib.Base64;
	import org.moyrax.nereyda.services.core.*;
	import org.moyrax.nereyda.services.errors.*;
	import org.moyrax.nereyda.services.template.*;
	
	public class JROIMContentFactory implements IContentFactory
	{
		public static const ENCODER_NONE   :String = "none";   // Los datos estarán en texto plano.
		public static const ENCODER_BASE64 :String = "base64"; // Los datos estarán codificados en Base64.

		/************************SINGLETON************************/
				
		private static var instance :IContentFactory = null;

		public static function getInstance():IContentFactory
		{
			if ( instance == null )
				instance = new JROIMContentFactory();
				
			return( instance );
		}
		
		/*********************************************************/

		[Bindable]
		public var encoder :String;
		
		[Bindable]
		public var mappings :IMappingController;
		
		public function parseResponse( responseEvent:Event ):IServiceResponse
		{
			var respStr  :String = responseEvent.target.data;
			var response :Response = new Response();
			var respObj  :IServiceObject = null;
			
			var errorCheck :int = respStr.toLocaleLowerCase().indexOf( "fatal error" );
			
			if ( errorCheck > -1 ) {
				return(null);
			}
			
			response.parse( respStr );

			if ( response.error ) {
				return(null); // El servicio devolvió un error.
			}
			
			// Verifica si el servicio que devolvió la respuesta tiene
			// ServiceObjects asociados en el archivo de mapping.
			//
			if ( this.mappings.getObjects( response.service ) != null ) 
			{
				var objects  :ArrayCollection = this.mappings.getObjects( response.service );
				var mapClass :Class = null;
				var item     :MappingEntry;
				
				// Busca el ServiceObject asociado con esta respuesta.
				//
				for each ( item in objects )
				{
					if ( item.endpointName == response.endpointName ) {
						mapClass = getClassByAlias(item.object);
						
						break;
					}
				}
				
				// Verifica que el Service Object para la respuesta
				// recibida, exista, de lo contrario desencadena un
				// error.
				//
				if ( mapClass != null ) {
					respObj = new mapClass();
					respObj.makeFromResponse( response );
				}
				else {
					throw EndpointNotFoundError(null);
				}
				
				// Crea los VO para esta respuesta.
				//
				respObj.makeValueObjects();
			}
			
			return( respObj );
		}

		public function parseError( errorEvent:Event ):IServiceResponse
		{
			var response :Response = new Response();
			var error    :ServiceError = new ServiceError(null);

			response.parse( errorEvent.target.data );
	
			error.makeFromResponse( response );
			
			if ( error.code == ServiceError.UNKNOWN_ERROR )
			{
				error.message = errorEvent.target.data;
			}
			
			return(error);
		}

		public function makeRequestStr( request:Request ):String
		{
			var strParam   :String = request.params.serialize( Parameter.SERIAL_OBJECT );
			var strRequest :String = "rq=" + Base64.Encode(strParam) + "&enc=" + this.encoder;

			return( strRequest );
		}

		public function makeRequest( request:Request ):Object
		{
			var reqObj    :Object = {};
			var itemName  :String;
			var itemValue :*;
			
			for ( var i:int = 0; i < request.params.length; i++ )
			{
				itemName  = request.params.getItemName(i);
				itemValue = request.params.getItem(i);
				
				reqObj[ itemName ] = itemValue;
			}

			return( reqObj );
		}
		
		public function createEvent( serviceObject:IServiceObject ):IServiceEvent
		{
			if ( !serviceObject )
				return(null);
			
			var event :Class = this.mappings.getObjectEvent( serviceObject );

			return( new event( serviceObject ) );
		}
		
		private function parseServerError( response:String ):Object
		{
			return(null);
		}
	}
}